package org.putrpctorest.parameter.impl;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.putrpctorest.parameter.JavaParameterNameDiscover;
import org.putrpctorest.parameter.Mapping;
import org.putrpctorest.resource.Parameter;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class MappingImpl implements Mapping {

	private Expressions restToJavaExpressions;
	private Expressions javaToRestExpressions;
	private int javaParametersSize;

	@Override
	public void config(List<Parameter> restParameterDefinitions,
			Method javaServiceMethod,
			JavaParameterNameDiscover javaParameterNameDiscover,
			Map<String, String> nameCorrespondence) {
		
		javaParametersSize = javaServiceMethod.getParameterTypes().length;
		
		Definitions restParameters = DefinitionsFactory
				.getInstance().create(restParameterDefinitions);
		
		Definitions javaParameters = DefinitionsFactory
				.getInstance().create(javaServiceMethod,
						javaParameterNameDiscover);

		Match match = restParameters.associate(javaParameters);
		restToJavaExpressions = match.getExpressions(restParameters.getDescription());
		javaToRestExpressions = match.getExpressions(javaParameters.getDescription());
	}

	@Override
	public Object[] getJavaParameters(Map<String, Object> restParameters) {
		Object[] javaParameters = new Object[javaParametersSize];
		RootExpressionObject root = createRootExpressionObject(javaParameters,
				restParameters);
		EvaluationContext evContext = new StandardEvaluationContext(root);
		restToJavaExpressions.eval(evContext);
		return root.getJavaParams();
	}

	@Override
	public Map<String, Object> getRestParameters(Object[] javaParameters) {
		Map<String, Object> restParameters = new HashMap<String, Object>();
		RootExpressionObject root = createRootExpressionObject(javaParameters,
				restParameters);
		EvaluationContext evContext = new StandardEvaluationContext(root);
		javaToRestExpressions.eval(evContext);
		return root.getRestParams();
	}

	private RootExpressionObject createRootExpressionObject(
			Object[] javaParameters, Map<String, Object> restParameters) {
		RootExpressionObject root = new RootExpressionObject();
		root.setJavaParams(javaParameters);
		root.setRestParams(restParameters);
		return root;
	}

}
